package com.unitd.frame.sso.web.interceptor;

import com.unitd.frame.sso.annotation.Action;
import com.unitd.frame.sso.annotation.Login;
import com.unitd.frame.sso.common.config.SSOConfig;
import com.unitd.frame.sso.common.helper.SSOHelper;
import com.unitd.frame.sso.common.token.Token;
import com.unitd.frame.comm.utils.http.HttpUtils;
import com.unitd.frame.sso.web.handler.ISSOHandler;
import com.unitd.frame.sso.web.handler.impl.DefaultSSOHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @desc 登录权限验证的Spring拦截器,在调用Spring的Controller方法之前调用处理;
 * 使用此类的前提是对应的工程需要引入相应的Spring的jar包
 * @filename SSOSpringInterceptor.java
 * @copyright www.unitd.com
 * @author Hudan
 * @version 1.0
 * @date 2016/10/14
 */
public class SSOSpringInterceptor extends HandlerInterceptorAdapter {

	private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());

	private ISSOHandler ssoHandler;

	/**
	 * @desc Spring的拦截器默认调用方法
	 * 执行登录权限验证,此方法在调用SprigMVC的Controller的处理方法之前进行拦截调用
	 * @param request http请求对象
	 * @param response http响应对象
	 * @param handler 默认的SSO Handler拦截器
	 * @return 登录用户是否有权限
	 * @throws Exception
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		Token token = SSOHelper.getToken(request);
		if (token != null) {
			/* 正常请求,request 设置 token 减少二次解密 */
			request.setAttribute(SSOConfig.SSO_TOKEN_ATTR, token);
		}

		/* 处理 Controller 方法; 判断 handler 是否为 HandlerMethod 实例 */
		if (handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;
			Method method = handlerMethod.getMethod();
			Login login = method.getAnnotation(Login.class);
			if (login != null) {
				if (login.action() == Action.Skip) {
					// 当使用@Login(action = Action.Skip)自定义注解时,忽略此拦截
					return true;
				}
			}

			// 正常执行拦截处理
			if (token == null) {
				if ( HttpUtils.isAjax(request) ) {
					/* Handler 处理 AJAX 请求 */
					this.getSsoHandler().preTokenIsNullAjax(request, response);
					return false;
				} else {
					/* token 为空,调用 Handler 处理; 返回 true 继续执行,清理登录状态并重定向至登录界面 */
					if (this.getSsoHandler().preTokenIsNull(request, response)) {
						logger.info("退出登录的URL:" + request.getRequestURL());
						SSOHelper.clearRedirectLogin(request, response);
					}
					return false;
				}
			}
		}

		/* 通过拦截 */
		return true;
	}

	public ISSOHandler getSsoHandler() {
		if (ssoHandler == null) {
			return DefaultSSOHandler.getInstance();
		}
		return ssoHandler;
	}

	public void setSsoHandler(ISSOHandler ssoHandler) {
		this.ssoHandler = ssoHandler;
	}
}